package com.wpam.scrabble.mobile.communication;

import com.wpam.scrabble.mobile.GameLogic;
import com.wpam.scrabble.mobile.activities.PlayerInfo;
import com.wpam.scrabble.mobile.activities.PlayersWaitingActivity;
import com.wpam.scrabble.mobile.messages.InfoMessage;
import com.wpam.scrabble.mobile.messages.Message;
import com.wpam.scrabble.mobile.messages.MoveMessage;
import com.wpam.scrabble.mobile.messages.MsgSerializer;
import com.wpam.scrabble.mobile.messages.NewLettersMessage;

public class ServerMessageParserThread extends Thread {

	private MsgBuffer buffer_;
	private boolean running_;
	
	public ServerMessageParserThread(MsgBuffer buffer) {

		this.buffer_ = buffer;
		this.running_ = false;
	}
	
	@Override
	public void run() {

		buffer_.start();
		running_ = true;
		Message messageToProcess;
		GameLogic gameLogic = GameLogic.getInstance();
		while (running_) {
			messageToProcess = buffer_.take();
			assert messageToProcess.getSenderDevice() != null : "NULL message sender in serverMessageParser, msgType = " + messageToProcess.getType();
			if (!running_)
				return;
			if (messageToProcess.getType() == Message.INFO
					|| messageToProcess.getType() == Message.START
					|| messageToProcess.getType() == Message.NEW_TURN
					|| messageToProcess.getType() == Message.NEW_LETTERS
					|| messageToProcess.getType() == Message.PAUSE)
				assert false : "Server Received message of type " + messageToProcess.getType();
			
			if (messageToProcess.getType() == Message.CONNECT) {
				try {
					if (!gameLogic.isGameRunning()) {
						((PlayersWaitingActivity) CommunicationManager.getInstance().getCurrentActivity()).addUserToList(new PlayerInfo(messageToProcess.getSenderDevice()));
						CommunicationManager.getInstance().sendServerInfo(messageToProcess.getSenderDevice());
					} else {
						if (gameLogic.canPlayerJoinGame(messageToProcess.getSenderDevice()))
							CommunicationManager.getInstance().sendDumpInfo(messageToProcess.getSenderDevice());
						else {
							// Refuse connection
							CommunicationManager.writeAsServer(messageToProcess.getSenderDevice(), MsgSerializer.serialize(new InfoMessage()));
							CommunicationManager.getInstance().disconnectSingleClient(messageToProcess.getSenderDevice());
						}
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					// when receiver is not found within connected clients
					e.printStackTrace();
				}
			}
			if (messageToProcess.getType() == Message.READY)
				((PlayersWaitingActivity)CommunicationManager.getInstance().getCurrentActivity()).setUserReady(new PlayerInfo(messageToProcess.getSenderDevice()));
			String senderName = gameLogic.getPlayerManager().getNameOfSender(messageToProcess.getSenderDevice());
			if (gameLogic.isGameRunning()) {
				switch (messageToProcess.getType()) {
				case Message.MOVE:
					gameLogic.stopTimer();
					MoveMessage moveMsg = (MoveMessage) messageToProcess;
					
					if (moveMsg.getMoveInfo() != null) {
						gameLogic.applyOuterMove(moveMsg.getMoveInfo());
						gameLogic.getScoreBoard().addPlayerPoints(senderName, moveMsg.getMoveInfo().getPoints());
						
						String newLetters = gameLogic.updatePlayersLetters(senderName, moveMsg.getMoveInfo().getLetters());
						try {
							CommunicationManager.writeAsServer(moveMsg.getSenderDevice(), MsgSerializer.serialize(new NewLettersMessage(newLetters)));
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					else if (moveMsg.getLettersToChange() != null) {
						String newLetters = gameLogic.changeLettersOfPlayer(senderName, moveMsg.getLettersToChange());
						try {
							CommunicationManager.writeAsServer(moveMsg.getSenderDevice(), MsgSerializer.serialize(new NewLettersMessage(newLetters)));
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					else if (moveMsg.isGiveUp())
						gameLogic.getScoreBoard().setPlayerDone(senderName);
					
					gameLogic.moveNotifier(moveMsg);
					CommunicationManager.getInstance().sendMoveAndNextTurnMsgToEverybody(moveMsg);
					if (gameLogic.isGameEnded()) 
						gameLogic.pauseGame(GameLogic.PLAYERS_DONE);
					else
						gameLogic.startTimer();
					break;
				case Message.GOODBYE:
					CommunicationManager.getInstance().disconnectSingleClient(messageToProcess.getSenderDevice());
					gameLogic.playerDisconnected(senderName);
					break;
				default:
					break;
				}
			}
		}
		running_ = false;
	}

	@Override
	public void interrupt() {

		running_ = false;
		buffer_.endWork();
		super.interrupt();
	}
	
}
